/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 gtkmm.cc                                                  VLC Gtkmmm gui module
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Copyright © 2006-2008 the VideoLAN team

 Authors: David GUGLIELMI <raxxx.fr@gmail.com>
          David LARROQUE <david.larroque@gmail.com>

 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation; either version 2 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but WITHOUT ANY
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE. See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 Street, Fifth Floor, Boston MA 02110-1301, USA.
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

#include <gtkmm/calendar.h>
#include <gtkmm/main.h>
#include <gtkmm/window.h>

#include <assert.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gtkmm.hh"
#include "main_interface.hh"
#include "dialogs_provider.hh"
#include "input_manager.hh"

#include <vlc_plugin.h>
#include <vlc_window.h>

#include "../../../share/vlc32x32.xpm"
#include "../../../share/vlc32x32-christmas.xpm"

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int open_vlc (vlc_object_t *);
static int open_dialogs (vlc_object_t *);
static void close_vlc (vlc_object_t *);
static void run (intf_thread_t *);
static void *init (vlc_object_t *);
static void show_dialog (intf_thread_t *, int, int, intf_dialog_args_t *);
static int popup_menu_cb (vlc_object_t *, const char *, vlc_value_t,\
                        vlc_value_t, void *);
static int window_open (vlc_object_t *);
static int window_control (vout_window_t *, int, va_list);
static int window_close (vlc_object_t *);

//Glib::Mutex::Mutex windowLock;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vlc_module_begin ();
  
  set_shortname ("Gtkmm");
  set_description (_("Gtkmm interface"));
  set_category (CAT_INTERFACE);
  set_subcategory (SUBCAT_INTERFACE_MAIN);
  set_capability ("interface", 151);
  set_callbacks (open_vlc, close_vlc);

  add_shortcut ("gtkmm");

  add_submodule ();
    set_description ("Dialog provider");
    set_capability ("dialogs provider", 51);
    set_callbacks (open_dialogs, close_vlc);

  // TODO

/*
  add_submodule ();
    set_capability ("vout window", 50);
    set_callbacks (window_open, window_close);
*/

vlc_module_end ();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
open_vlc (vlc_object_t *p_this)
{

  intf_thread_t *p_intf = (intf_thread_t *)p_this;

  // FIXME: Is a X Display check needed.

  // Allocations
  p_intf->p_sys = (intf_sys_t *)malloc (sizeof (intf_sys_t));
  
  if (!p_intf->p_sys)
    return VLC_ENOMEM;
    
  memset (p_intf->p_sys, 0, sizeof (intf_sys_t));

  p_intf->pf_run = run;

  // Access to the playlist
  p_intf->p_sys->p_playlist = pl_Yield (p_intf);

  // Listen to the messages
  p_intf->p_sys->p_sub = msg_Subscribe (p_intf);

  // What is that ?
  // FIXME var_Create (p_this, "window_widget", VLC_VAR_ADDRESS);
  
  return VLC_SUCCESS;

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
open_dialogs (vlc_object_t *p_this)
{

  intf_thread_t *p_intf = (intf_thread_t *)p_this;

  int val = open_vlc (p_this);
  
  if (val)
    return val;

  p_intf->pf_show_dialog = show_dialog;
  
  return VLC_SUCCESS;

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
close_vlc (vlc_object_t *p_this)
{

  intf_thread_t *p_intf = (intf_thread_t *)p_this;

  // TODO DialogProvider event
  if (p_intf->p_sys->b_isDialogProvider)
   {
    //vlc_thread_join (p_intf);
   }

  vlc_object_release (p_intf->p_sys->p_playlist);
  msg_Unsubscribe (p_intf, p_intf->p_sys->p_sub);
  free (p_intf->p_sys);

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Initialize the interface or the dialogs provider
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
run (intf_thread_t *p_intf)
{

  if (p_intf->pf_show_dialog)
   {
    if (vlc_thread_create (p_intf, "Gtkmm dialogs", init, 0, true))
      msg_Err (p_intf, "failed to create Gtkmm dialogs thread");
   }
  else
   init (VLC_OBJECT (p_intf));

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// TODO Mutex & wait condition
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
*init (vlc_object_t *obj)
{

  intf_thread_t *p_intf = (intf_thread_t *)obj;
  vlc_value_t val;
  int argc = 1;
  char *args[] = {(char*)"", "\0"};
  char **argv  = args;

  Gtk::Main app (argc, argv);
  // FIXME what about p_intf->p_sys->p_app = app;

/*  
  if (!Glib::thread_supported ())
    Glib::thread_init ();
*/

  Glib::Date date;
  Gtk::Calendar ().get_date (date);

  // Icon setting
  if (date.get_day_of_year () >= 354)
    Gtk::Window::set_default_icon (\
      Gdk::Pixbuf::create_from_xpm_data (vlc_christmas_xpm)\
    );
  else
     Gtk::Window::set_default_icon (\
       Gdk::Pixbuf::create_from_xpm_data (vlc_xpm)\
     );

  // Initialize timers and the Dialog Provider
  DialogsProvider::getInstance (p_intf);

  // TODO main interface pointer ??

  if (!p_intf->pf_show_dialog)
   {
    // Here we call start the main interface
    // FIXME: Why not send the p_intf ??
    vlc_value_t val;
    
    p_intf->p_sys->p_mi = new MainInterface::MainInterface (p_intf);
 
    var_Set (p_intf, "window_widget", val);
   // TODO Mutex
    p_intf->p_sys->b_isDialogProvider = false;
   }
  else
   {
    vlc_thread_ready (p_intf);
    p_intf->p_sys->b_isDialogProvider = true;
   }

  // Give instructions to the VLC core
  p_intf->pf_show_dialog = show_dialog;

  // TODO add NLS support and get last path

  app.run ();

  // TODO another mutex stuff

  // Destroy 1st the main interface because of MainInputManager connections
  delete p_intf->p_sys->p_mi;

  // Destroy then other windows connected to DialogsProvider & MainInputManager
  DialogsProvider::killInstance ();
  MainInputManager::killInstance ();

  // FIXME Need to Delete the application

  // TODO Save the path

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
show_dialog (intf_thread_t *p_intf, int i_dialog_event, int i_arg,\
             intf_dialog_args_t *p_arg)
{

  // TODO Tell the core how to show a dialog

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
popup_menu_cb (vlc_object_t *p_this, const char *psz_variable,\
               vlc_value_t old_val, vlc_value_t new_val, void *param)
{

  intf_thread_t *p_intf = (intf_thread_t *)param;
  
  show_dialog (p_intf, INTF_DIALOG_POPUPMENU, new_val.b_bool, 0);
  
  return VLC_SUCCESS;

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Video Provider here
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
window_open (vlc_object_t *obj)
{

  vout_window_t *wnd = (vout_window_t *)obj;

  if (config_GetInt (obj, "embedded-video") <= 0)
    return VLC_EGENERIC;

  intf_thread_t *intf = (intf_thread_t *)
    vlc_object_find_name (obj, "gtkmm", FIND_ANYWHERE);

  if (intf == NULL)
    return VLC_EGENERIC;
    
  assert (intf->i_object_type == VLC_OBJECT_INTF);

  //var_Create (intf, "window_widget", VLC_VAR_ADDRESS);

  // TODO Waiting for interface

  // TODO Resquesting window

  return VLC_SUCCESS;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
WindowControl (vout_window_t *wnd, int query, va_list args)
{
  // TODO
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
window_close (vlc_object_t *obj)
{

  vout_window_t *wnd = (vout_window_t *)obj;
  // TODO

}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
